load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load("//tachyon/math/elliptic_curves/bls12/generator:build_defs.bzl", "generate_bls12_curves")
load("//tachyon/math/elliptic_curves/short_weierstrass/generator:build_defs.bzl", "generate_ec_points")
load(
    "//tachyon/math/finite_fields/generator/ext_field_generator:build_defs.bzl",
    "generate_fp12s",
    "generate_fp2s",
    "generate_fp6s",
)
load(
    "//tachyon/math/finite_fields/generator/prime_field_generator:build_defs.bzl",
    "SMALL_SUBGROUP_ADICITY",
    "SMALL_SUBGROUP_BASE",
    "SUBGROUP_GENERATOR",
    "generate_large_fft_prime_fields",
)

package(default_visibility = ["//visibility:public"])

string_flag(
    name = "fq_" + SMALL_SUBGROUP_ADICITY,
    build_setting_default = "2",
)

string_flag(
    name = "fq_" + SMALL_SUBGROUP_BASE,
    build_setting_default = "3",
)

string_flag(
    name = "fq_" + SUBGROUP_GENERATOR,
    build_setting_default = "2",
)

# Parameters are from https://zips.z.cash/protocol/protocol.pdf#page=98 and https://github.com/arkworks-rs/curves/tree/master/bls12_381/src/fields
generate_large_fft_prime_fields(
    name = "fq",
    class_name = "Fq",
    # Hex: 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
    modulus = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787",
    namespace = "tachyon::math::bls12_381",
    small_subgroup_adicity = ":fq_" + SMALL_SUBGROUP_ADICITY,
    small_subgroup_base = ":fq_" + SMALL_SUBGROUP_BASE,
    subgroup_generator = ":fq_" + SUBGROUP_GENERATOR,
)

string_flag(
    name = "fr_" + SMALL_SUBGROUP_ADICITY,
    build_setting_default = "1",
)

string_flag(
    name = "fr_" + SMALL_SUBGROUP_BASE,
    build_setting_default = "3",
)

string_flag(
    name = "fr_" + SUBGROUP_GENERATOR,
    build_setting_default = "7",
)

generate_large_fft_prime_fields(
    name = "fr",
    class_name = "Fr",
    # Hex: 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
    modulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513",
    namespace = "tachyon::math::bls12_381",
    small_subgroup_adicity = ":fr_" + SMALL_SUBGROUP_ADICITY,
    small_subgroup_base = ":fr_" + SMALL_SUBGROUP_BASE,
    subgroup_generator = ":fr_" + SUBGROUP_GENERATOR,
)

generate_fp2s(
    name = "fq2",
    base_field = "Fq",
    base_field_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/fq.h",
    class_name = "Fq2",
    is_packed = False,
    namespace = "tachyon::math::bls12_381",
    non_residue = ["-1"],
    deps = [":fq"],
)

generate_fp6s(
    name = "fq6",
    base_field = "Fq2",
    base_field_degree = 2,
    base_field_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/fq2.h",
    class_name = "Fq6",
    is_packed = False,
    mul_by_non_residue_override =
        """    // (c0 + c1 * u) * (1 + u) = (c0 - c1) + (c1 + c0) * u
    return BaseField(v.c0() - v.c1(), v.c0() + v.c1());""",
    namespace = "tachyon::math::bls12_381",
    non_residue = [
        "1",
        "1",
    ],
    deps = [":fq2"],
)

generate_fp12s(
    name = "fq12",
    base_field = "Fq6",
    base_field_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/fq6.h",
    class_name = "Fq12",
    is_packed = False,
    namespace = "tachyon::math::bls12_381",
    non_residue = [
        "0",
        "1",
        "0",
    ],
    deps = [":fq6"],
)

generate_ec_points(
    name = "g1",
    a = ["0"],
    b = ["4"],
    base_field = "Fq",
    base_field_degree = 1,
    base_field_dep = ":fq",
    base_field_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/fq.h",
    class_name = "G1",
    # Hex: 0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe
    endomorphism_coefficient = ["793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"],
    gen_gpu = True,
    # Optimal decomposition as per Ch. 6.3.2: Decompositions for the k = 12 BLS
    # Family, from Guide to Pairing Based Cryptography by El Mrabet
    glv_coeffs = [
        # X²
        # Hex: 0xac45a4010001a4020000000100000000
        "228988810152649578064853576960394133504",
        "1",
        "-1",
        # X² - 1
        # Hex: 0xac45a4010001a40200000000ffffffff
        "228988810152649578064853576960394133503",
    ],
    # Hex: 0x73eda753299d7d483339d80809a1d804a7780001fffcb7fcfffffffe00000001
    lambda_ = "52435875175126190479447740508185965837461563690374988244538805122978187051009",
    namespace = "tachyon::math::bls12_381",
    scalar_field = "Fr",
    scalar_field_dep = ":fr",
    scalar_field_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/fr.h",
    # Hex: 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb
    x = ["3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507"],
    # Hex: 0x8b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1
    y = ["1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569"],
)

generate_ec_points(
    name = "g2",
    a = [
        "0",
        "0",
    ],
    b = [
        "4",
        "4",
    ],
    base_field = "Fq2",
    base_field_degree = 2,
    base_field_dep = ":fq2",
    base_field_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/fq2.h",
    class_name = "G2",
    endomorphism_coefficient = [
        # Hex: 0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe
        "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350",
        "0",
    ],
    glv_coeffs = [
        # Hex: 0xac45a4010001a40200000000ffffffff
        "-228988810152649578064853576960394133503",
        "1",
        "-1",
        # Hex: 0xac45a4010001a4020000000100000000
        "-228988810152649578064853576960394133504",
    ],
    # Hex: 0xac45a4010001a40200000000ffffffff
    lambda_ = "228988810152649578064853576960394133503",
    namespace = "tachyon::math::bls12_381",
    scalar_field = "Fr",
    scalar_field_dep = ":fr",
    scalar_field_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/fr.h",
    x = [
        # Hex: 0x24aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8
        "352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160",
        # Hex: 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e
        "3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758",
    ],
    y = [
        # Hex: 0xce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801
        "1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905",
        # Hex: 0x606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be
        "927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582",
    ],
)

generate_bls12_curves(
    name = "bls12_381",
    class_name = "BLS12_381",
    fq12_dep = ":fq12",
    fq12_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/fq12.h",
    g1_dep = ":g1",
    g1_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/g1.h",
    g2_dep = ":g2",
    g2_hdr = "tachyon/math/elliptic_curves/bls12/bls12_381/g2.h",
    namespace = "tachyon::math::bls12_381",
    twist_type = "M",
    # Hex: 0xd201000000010000
    x = "-15132376222941642752",
)
